import _ from 'lodash';
import Vue from 'vue';

const ctx = '@@Drag'; //eslint-disable-line

const isServer = true;
// === base ===

let isAttached = function (element) { //eslint-disable-line
        let currentNode = element.parentNode;
        while (currentNode) {
            if (currentNode.tagName === 'HTML') return true;
            if (currentNode.nodeType === 11) return false;
            currentNode = currentNode.parentNode;
        }
        return false;
    },
    unbind = function() {
        this.el.removeEventListener('mousedown', _mousedown.bind(this));
    },
    doBind = function() {
        if (!this) return;
        if (this.binded) return; // eslint-disable-line
        this.binded = true;

        // console.log('v-drag.doBind: ', this.el.getAttribute('drag-val'));
        this.el.addEventListener('mousedown', _mousedown.bind(this));
    },
    _mousedown = function(e) {
        e.preventDefault();
        this.startX = e.clientX;
        this.startY = e.clientY;
        document.onmousemove = _.throttle(_mousemove.bind(this), 50);
        document.onmouseup = _mouseup.bind(this);
    },
    _mousemove = function(e) {
        e.preventDefault();
        let x = e.clientX - this.startX,
            y = e.clientY - this.startY;
        this.vm.$data[this.el.getAttribute('drag-val')] = { x, y };
    },
    _mouseup = function(e) {
        e.preventDefault();
        document.onmousemove = null;
        document.onmouseup = null;
        let func = this.vm[this.el.getAttribute('end-func')];
        // console.log('v-drag._mouseup: ', this.el.getAttribute('end-func'));
        if (typeof func === 'function') func(e);
    };

// === kernal===

let Drag = {
    bind(el, binding, vnode) {
        el[ctx] = {
            el,
            vm: vnode.context,
            expression: binding.value
        };
        const args = arguments;
        el[ctx].vm.$nextTick(() => {
            if (isAttached(el)) {
                setTimeout(() => {
                    doBind.call(el[ctx], args);
                }, 0);
                return;
            }

            el[ctx].bindTryCount = 0;

            let tryBind = function() {
                if (el[ctx].bindTryCount > 10) return; //eslint-disable-line
                el[ctx].bindTryCount++;
                if (isAttached(el)) {
                    doBind.call(el[ctx], args);
                } else {
                    setTimeout(tryBind, 50);
                }
            };

            // tryBind();
            setTimeout(tryBind, 0);
        });
    },

    unbind(el) {
        el[ctx].unbinded = true;
        unbind.call(el[ctx]);
    }
};

// === install ===

const install = function(Vue) {
    Vue.directive('Drag', Drag);
};

if (!isServer && window.Vue) {
    window.Kernal = Drag;
    Vue.use(install); // eslint-disable-line
}

Drag.install = install;
export default Drag;
